package com.rxst.msg.sso.interceptor;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpStatus;
import cn.hutool.json.JSONUtil;
import com.rxst.msg.base.ResponseVo;
import com.rxst.msg.server.MsgxIpService;
import com.rxst.msg.sso.entity.UserContext;
import com.rxst.msg.utils.IpUtil;
import com.rxst.msg.utils.TokenUtils;
import io.swagger.models.HttpMethod;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.List;

/**
 * @author ：唐建军
 * @date ：2021/8/19 18:28
 * @description：配置拦截去
 * @modified By：
 * @version: $
 */
@Order(1)
@Slf4j
@Component
public class LoginInterceptor implements HandlerInterceptor {

    @Value("${sso.enable}")
    private boolean sso;

    @Value("${sso.ip:}")
    private String ip;

    @Autowired
    private MsgxIpService ipService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) {
        //String ipAddr = IpUtil.getIpAddr(request);
        String ipAddr = request.getRemoteAddr();
        String requestUrl = request.getRequestURI();
        log.info("url:" + requestUrl);
        log.info("Remote ip:" + ipAddr);

        if (StrUtil.isNotBlank(requestUrl) && (requestUrl.contains("swagger-ui") || requestUrl.contains("v3/api-docs") || requestUrl.contains("/plugFlow/list"))) {
            //swagger 直接放行
            return true;
        }
        log.info("检验sso:" + sso);
        if (sso) {
            log.info("直接放行");
            return true;
        }

        if (HttpMethod.OPTIONS.toString().equals(request.getMethod())) {
            //预请求
            return true;
        }

        if (requestUrl.contains("/ip/cache")) {
            return true;
        }

        // 白名单判断: 服务器本机iP直接放行，其他ip做校验
        if (!StrUtil.equals(ipAddr, ip) && !IpUtil.containsIp(ipAddr)) {
            return noServe(request, response);
        }

        // 排除不需要token的url
        List<String> excludePath = ipService.excludePath();
        if (excludePath.contains(requestUrl)) {
            return true;
        }
        //用户已登录
        String token = request.getHeader("token");
        if (StrUtil.isBlank(token)) {
            token = request.getParameter("token");
        }

        //判断全局token是否存在token
        if (StrUtil.isNotBlank(token) && TokenUtils.checkToken(token)) {
            UserContext userContext = TokenUtils.getUserContext(token);
            if (userContext == null) {
                return toLogin(request, response);
            }
            UserContext.setLocalUserContext(userContext);
            // 不需要验证接口的url
            List<String> excludeTokenPath = ipService.excludeTokenPath();
            if (excludeTokenPath.contains(requestUrl)) {
                return true;
            }
            // 接口权限验证
            if (!userContext.authMenu(requestUrl)) {
                return noAuth(request, response);
            }
        } else {
            return toLogin(request, response);
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

    }

    /**
     * ip 不在服务范围内
     *
     * @param response
     * @return
     */
    private boolean noServe(HttpServletRequest request, HttpServletResponse response) {
        responseMessage(request, response, "不在服务范围内", HttpStatus.HTTP_UNAUTHORIZED);
        return false;
    }

    /**
     * url 没有访问权限
     *
     * @param response
     * @return
     */
    private boolean noAuth(HttpServletRequest request, HttpServletResponse response) {
        responseMessage(request, response, "没有访问权限", HttpStatus.HTTP_UNAUTHORIZED);
        return false;
    }

    /**
     * 没有token 需要登录
     *
     * @param response
     * @return
     */
    private boolean toLogin(HttpServletRequest request, HttpServletResponse response) {
        responseMessage(request, response, "用户未登录", HttpStatus.HTTP_UNAUTHORIZED);
        return false;
    }

    private void responseMessage(HttpServletRequest request, HttpServletResponse response, String msg, int code) {
        try {
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json;charset=utf-8");
            response.addHeader("Access-Control-Allow-Headers", "*");
            response.addHeader("Access-Control-Max-Age", "3600");
            PrintWriter printWriter = response.getWriter();
            printWriter.print(JSONUtil.toJsonStr(ResponseVo.error(msg, code)));
            printWriter.flush();
            printWriter.close();
        } catch (Exception e) {
            log.error("校验token错误", e);
        }
    }
}
